package com.dingyx.ps.filter;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.dingyx.ps.mapper.EnterpriseMapper;
import com.dingyx.ps.mapper.UserMapper;
import com.dingyx.ps.model.entity.EnterpriseDTO;
import com.dingyx.ps.model.entity.UserDTO;
import com.dingyx.ps.model.vo.BossUserVO;
import com.dingyx.ps.model.vo.EnterpriseUserVO;
import com.dingyx.ps.repository.UserCacheRepository;
import com.dingyx.ps.model.ReturnT;
import com.dingyx.ps.model.vo.AccountVO;
import com.dingyx.ps.util.Constant;
import com.dingyx.ps.util.ThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.RequestFacade;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;

/**
 * @author dingyuxin
 *
 */
@Slf4j
//@Component
//@WebFilter(filterName="LoginValidateFilter", urlPatterns="/admin/*")
//@RefreshScope
public class LoginValidateFilter implements Filter {
    @Autowired
    private UserCacheRepository userCacheRepository;
    @Resource
    private UserMapper userMapper;
    @Resource
    private EnterpriseMapper enterpriseMapper;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        String token =  ((RequestFacade) servletRequest).getHeader("token");
        if(StringUtils.isBlank(token)) {
            token = servletRequest.getParameter("token");
        }
        log.info("验证用户登陆信息:{}", token);
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        String path = request.getRequestURI();
        List<String> ignoreUrls = Arrays.asList("swagger", "favicon.ico", "/v2/api-docs",
               "/loginIn", "/logout","/thirtyPart", "upload", "/callback", "sendEngineerLoginSMS", "/receiveUpgPayResult",
                "/receiveData", "/heart","/checkEngineerInfo");
        // 判断当前链接是否不需要登录教研
        String existIgnoreUrl = ignoreUrls.stream().
                filter(b -> path.contains(b)).
                findAny().orElse(null);
        if(Objects.nonNull(existIgnoreUrl)){
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        //兼容xnToken处理
        if(StringUtils.isBlank(token)){
            token = this.getTokenFromRequest(request);
        }
        if(StringUtils.isNotBlank(token)) {
            // 获取用户信息
            AccountVO userInfo = userCacheRepository.getUserObject(token);
            if(Objects.isNull(userInfo)){
                outPutErrorResponse(servletResponse);
                return;
            }
            ThreadLocalUtil.setAccount(userInfo);
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            outPutErrorResponse(servletResponse);
            return;
        }
        //todo 不会拦截登陆
        filterChain.doFilter(servletRequest, servletResponse);
    }

    /**
     * 返回默认的登录异常
     * @param servletResponse
     * @throws IOException
     */
    private void outPutErrorResponse(ServletResponse servletResponse) throws IOException {
        servletResponse.setContentType("application/json; charset=utf-8");
        servletResponse.setCharacterEncoding("UTF-8");
        ReturnT result = new ReturnT(401, "请登录");
        OutputStream out = servletResponse.getOutputStream();
        out.write(JSONObject.toJSONString(result).getBytes("UTF-8"));
        out.flush();
    }

    @Override
    public void destroy() {
    }

    /**
     * <在request中获取xnToken，如果存在会将其转换为本项目token，进行与贤牛平台用户体系的兼容处理>
     * 即：使用xnToken也可登录本系统
     * 说明：
     *  1.本系统仍保留自己原本的处理逻辑，使用自有token进行登录的校验；
     *  2.平台登录用户信息对象 BossUserVO 中添加 Map<String,String> tokens 属性，用于记录其他兼容系统的token值，key为系统标识，本系统的key为“yg”，值为对应系统的token值；
     *  3.由于保留的本系统原本的处理逻辑，所以暂没有使用core包，无法处理其中的日志与权限的功能。
     * @param servletRequest 请求对象
     * @return java.lang.String
     * @author ZhangYang
     * @date 2022/3/30 11:12
     */
    private String getTokenFromRequest(ServletRequest servletRequest){
        //平台token的key
        final String xnTokenParamKey = "xnToken";
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String xnToken = request.getHeader(xnTokenParamKey);
        if(StrUtil.isBlank(xnToken)){
            xnToken = request.getParameter(xnTokenParamKey);
        }
        if(StrUtil.isBlank(xnToken)){
            return null;
        }
        final String xnTokenRedisKey = "xnToken#"+xnToken;
        BossUserVO user= userCacheRepository.get(xnTokenRedisKey, BossUserVO.class);
        if(user==null || user.getId()==null || user.getTenantCode()==null){
            if (user.getTenantId()== null){
                return null;
            }
        }
        log.info("开始查询企业信息----->");
        String tenantCode = user.getTenantCode();
        if (StringUtils.isEmpty(tenantCode)){
            // 租户不存在按照企业ID查询
            tenantCode = String.valueOf(user.getTenantId());
        }
        EnterpriseDTO enterpriseDTO = enterpriseMapper.selectByTenantCode(tenantCode);
        if(Objects.isNull(enterpriseDTO)){
            log.info("商户不存在");
            return null;
        }
        UserDTO userDTO = userMapper.selectById(enterpriseDTO.getUserId());
        if(userDTO==null || userDTO.getUserType()!=1) {
            log.info("非商户用户");
            return null;
        }

        final String ygMapKey = "yg";
        Map<String, String> tokens = user.getTokens();
        if(tokens!=null && tokens.get(ygMapKey)!=null){
            return tokens.get(ygMapKey);
        }else {
            EnterpriseUserVO enterpriseUser = new EnterpriseUserVO();
            BeanUtils.copyProperties(userDTO, enterpriseUser);
            enterpriseUser.setEnterpriseId(enterpriseDTO.getId());
            enterpriseUser.setEnterpriseName(enterpriseDTO.getEnterpriseName());
            // 设置登录token
            String ygRedisKey = Constant.SESSION_KEY_ENTERPRISE + IdUtil.simpleUUID();
            enterpriseUser.setToken(ygRedisKey);
            enterpriseUser.setUserId(userDTO.getId());
            enterpriseUser.setTenantCode(enterpriseDTO.getTenantCode());
            // 缓存企业用户信息
            userCacheRepository.cacheUserInfo(ygRedisKey, enterpriseUser, Constant.SESSION_KEY_USER_EXPIRE);

            //转换token并更新xnToken至redis
            tokens = new HashMap<>();
            tokens.put(ygMapKey, ygRedisKey);
            user.setTokens(tokens);
            userCacheRepository.cacheUserInfo(xnTokenRedisKey, user, Constant.SESSION_KEY_USER_EXPIRE);
            return ygRedisKey;
        }
            /*final String ygMapKey = "yg";
            Map<String, String> tokens = user.getTokens();
            if(tokens!=null && tokens.get(ygMapKey)!=null){
                return tokens.get(ygMapKey);
            }else{

                UserDTO userDTO = userMapper.selectByMobilAndUserType(user.getPhone(), 1);//用户类型（0:灵活用工人员 1:商户 2:平台）
                if(UserStatusEnum.disable.equals(userDTO.getUserStatus())){
                    log.info("账号已被禁用");
                    return null;
                }
                EnterpriseUserVO enterpriseUser = new EnterpriseUserVO();
                BeanUtils.copyProperties(userDTO, enterpriseUser);
                EnterpriseDTO enterprise = enterpriseMapper.selectByUserId(userDTO.getId());
                if(Objects.isNull(enterprise)){
                    log.info("商户不存在");
                    return null;
                }
                enterpriseUser.setEnterpriseId(enterprise.getId());
                enterpriseUser.setEnterpriseName(enterprise.getEnterpriseName());
                // 设置登录token
                String ygRedisKey = Constant.SESSION_KEY_ENTERPRISE + IdUtil.simpleUUID();
                enterpriseUser.setToken(ygRedisKey);
                enterpriseUser.setUserId(userDTO.getId());
                enterpriseUser.setTenantCode(enterprise.getTenantCode());
                // 缓存企业用户信息
                userCacheRepository.cacheUserInfo(ygRedisKey, enterpriseUser, Constant.SESSION_KEY_USER_EXPIRE);

                //转换token并更新xnToken至redis
                tokens = new HashMap<>();
                tokens.put(ygMapKey, ygRedisKey);
                user.setTokens(tokens);
                userCacheRepository.cacheUserInfo(xnTokenRedisKey, user, Constant.SESSION_KEY_USER_EXPIRE);
                return ygRedisKey;*/
    }
}